package example;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import jvn.client.interfaces.JvnObjectI;
import jvn.client.JvnObjectImpl;
import jvn.client.interfaces.JvnObjectI;
import jvn.client.JvnServerImpl;
import jvn.client.JvnException;
import jvn.client.JvnAdvencedSharedObject;
import jvn.client.State;

//import spÃ©cifiques Ã  l'objet:

public class Jvn_Example extends Example implements JvnAdvencedSharedObject {

	private static final long serialVersionUID = 1L;
	private JvnObjectI jvnObjectImpl;
	private JvnServerImpl jvnServerImpl;
	private static String sharedObjectName = "Example";
	private example.Example sharedObjectBackUp = null;
	private boolean autolock = true;

	/**
	 * Les constructeurs
	 */

	public Jvn_Example() throws jvn.client.JvnException {

		jvnServerImpl = JvnServerImpl.jvnGetServer();

		jvnObjectImpl = jvnServerImpl.jvnLookupObject(sharedObjectName);

		if (jvnObjectImpl == null) {

			example.Example sharedObject =

			new Example();

			jvnObjectImpl = jvnServerImpl.jvnCreateObject(sharedObject);
			// after creation, I have a write lock on the object

			autolock = false;
			jvnUnLock();
			autolock = true;
			jvnServerImpl.jvnRegisterObject(sharedObjectName, jvnObjectImpl);
		}

	}

	public Jvn_Example(int p0, float p1, int p2) throws jvn.client.JvnException, java.lang.NullPointerException,
			java.lang.IndexOutOfBoundsException {

		jvnServerImpl = JvnServerImpl.jvnGetServer();

		jvnObjectImpl = jvnServerImpl.jvnLookupObject(sharedObjectName);

		if (jvnObjectImpl == null) {

			example.Example sharedObject =

			new Example(p0, p1, p2);

			jvnObjectImpl = jvnServerImpl.jvnCreateObject(sharedObject);
			// after creation, I have a write lock on the object

			autolock = false;
			jvnUnLock();
			autolock = true;
			jvnServerImpl.jvnRegisterObject(sharedObjectName, jvnObjectImpl);
		}

	}

	/**
	 * Les mÃ©thodes
	 */

	@Override
	public float interf1(int p0, int p1, java.lang.String p2) throws jvn.client.JvnException {
		float retour;
		try {

			if (autolock) {
				autolock = false;
				jvnLockWrite();
				autolock = true;
			}

			if (!(((JvnObjectImpl) jvnObjectImpl).jvnDebugGetLockState().equals(State.WLT))) {
				throw new JvnException(
						"Warning, you do a write without a write lock. You don't write into the shared object.");
			}

			retour = ((Example) jvnObjectImpl.jvnGetObjectState()).interf1(p0, p1, p2);
		} finally {
			if (autolock) {
				autolock = false;
				jvnUnLock();
				autolock = true;
			}
		}
		return retour;

	}

	@Override
	public void superMet1abstraite() throws jvn.client.JvnException {
		try {

			if (autolock) {
				autolock = false;
				jvnLockWrite();
				autolock = true;
			}

			if (!(((JvnObjectImpl) jvnObjectImpl).jvnDebugGetLockState().equals(State.WLT))) {
				throw new JvnException(
						"Warning, you do a write without a write lock. You don't write into the shared object.");
			}

			((Example) jvnObjectImpl.jvnGetObjectState()).superMet1abstraite();
		} finally {
			if (autolock) {
				autolock = false;
				jvnUnLock();
				autolock = true;
			}
		}

	}

	@Override
	public void interf2() throws jvn.client.JvnException {
		try {

			if (autolock) {
				autolock = false;
				jvnLockWrite();
				autolock = true;
			}

			if (!(((JvnObjectImpl) jvnObjectImpl).jvnDebugGetLockState().equals(State.WLT))) {
				throw new JvnException(
						"Warning, you do a write without a write lock. You don't write into the shared object.");
			}

			((Example) jvnObjectImpl.jvnGetObjectState()).interf2();
		} finally {
			if (autolock) {
				autolock = false;
				jvnUnLock();
				autolock = true;
			}
		}

	}

	@Override
	public void superMet1() throws jvn.client.JvnException {
		try {

			if (autolock) {
				autolock = false;
				jvnLockWrite();
				autolock = true;
			}

			if (!(((JvnObjectImpl) jvnObjectImpl).jvnDebugGetLockState().equals(State.WLT))) {
				throw new JvnException(
						"Warning, you do a write without a write lock. You don't write into the shared object.");
			}

			((Example) jvnObjectImpl.jvnGetObjectState()).superMet1();
		} finally {
			if (autolock) {
				autolock = false;
				jvnUnLock();
				autolock = true;
			}
		}

	}

	@Override
	public float superMet2Public(int p0) throws jvn.client.JvnException {
		float retour;
		try {

			if (autolock) {
				autolock = false;
				jvnLockWrite();
				autolock = true;
			}

			if (!(((JvnObjectImpl) jvnObjectImpl).jvnDebugGetLockState().equals(State.WLT))) {
				throw new JvnException(
						"Warning, you do a write without a write lock. You don't write into the shared object.");
			}

			retour = ((Example) jvnObjectImpl.jvnGetObjectState()).superMet2Public(p0);
		} finally {
			if (autolock) {
				autolock = false;
				jvnUnLock();
				autolock = true;
			}
		}
		return retour;

	}

	/**
	 * Les options avancÃ©es
	 */

	@Override
	public void jvnSetAutolock(boolean b) throws JvnException {
		if (transaction) {
			throw new JvnException("You cannot ask it during a transaction. Do a commit/rollback.");
		}
		this.autolock = b;

	}

	@Override
	public void jvnUnLock() throws JvnException {
		if (transaction) {
			throw new JvnException("You cannot ask it during a transaction. Do a commit/rollback.");
		}
		if (autolock) {
			throw new JvnException("You cannot ask it when autolock is enable.");
		}
		jvnObjectImpl.jvnUnLock();
	}

	@Override
	public void jvnLockRead() throws JvnException {
		if (transaction) {
			throw new JvnException("You cannot ask it during a transaction. Do a commit/rollback.");
		}
		if (autolock) {
			throw new JvnException("You cannot ask it when autolock is enable.");
		}
		jvnObjectImpl.jvnLockRead();
	}

	@Override
	public void jvnLockWrite() throws JvnException {
		if (transaction) {
			throw new JvnException("You cannot ask it during a transaction. Do a commit/rollback.");
		}
		if (autolock) {
			throw new JvnException("You cannot ask it when autolock is enable.");
		}
		jvnObjectImpl.jvnLockWrite();
	}

	boolean transaction = false;

	public static void jvnRename(String sharedObjectNameN) {
		sharedObjectName = sharedObjectNameN;

	}

	boolean lastautolock;

	@Override
	public void jvnBeginTransaction() throws JvnException {
		if (transaction) {
			throw new JvnException("You cannot ask it during a transaction. Do a commit/rollback.");
		}
		try {
			jvnObjectImpl.jvnLockWrite();
			lastautolock = autolock;
			this.autolock = false;
			transaction = true;

			// Write to disk with FileOutputStream
			FileOutputStream f_out = new FileOutputStream("myobject.data");

			// Write object with ObjectOutputStream
			ObjectOutputStream obj_out = new ObjectOutputStream(f_out);

			// Write object out to disk
			obj_out.writeObject(jvnObjectImpl.jvnGetObjectState()); // TODO
			// sharedObjectBackUp = (irc.Sentence) ((Sentence)jvnObjectImpl.jvnGetObjectState()).;

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public void jvnCommit() throws JvnException {
		transaction = false;
		jvnObjectImpl.jvnUnLock();
		autolock = lastautolock;

	}

	@Override
	public void jvnRollBack() throws JvnException {
		try {

			// Read from disk using FileInputStream
			FileInputStream f_in = new FileInputStream("myobject.data");

			// Read object using ObjectInputStream
			ObjectInputStream obj_in = new ObjectInputStream(f_in);

			// Read an object
			Object obj = obj_in.readObject();

			if (obj instanceof Example) {
				// Cast object to a Vector
				jvnObjectImpl.jvnSetObjectState((Example) obj);

				// Do something with vector....
			}
		} catch (IOException | ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		transaction = false;
		autolock = lastautolock;
	}

	@Override
	public String jvnGetLockState() {
		return ((JvnObjectImpl) jvnObjectImpl).jvnDebugGetLockState().toString();
	}

}